<!DOCTYPE html>
<html>
<head>
<title>Atomic Beam Apparatus</title>
<style>
  body {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
    background-color: #f0f0f0;
  }
  canvas {
    border: 1px solid #ccc;
    background-color: white;
  }
</style>
</head>
<body>
<canvas id="physicsCanvas" width="800" height="450"></canvas>
<script>
  const canvas = document.getElementById('physicsCanvas');
  const ctx = canvas.getContext('2d');

  // Style settings
  ctx.lineWidth = 2;
  ctx.strokeStyle = 'black';
  ctx.fillStyle = 'black';
  ctx.font = '20px "Comic Sans MS", cursive, sans-serif';
  ctx.textAlign = 'center';
  ctx.lineCap = 'round';

  const y_center = 200;

  // --- Helper Function ---
  function drawHatchedSlit(x, y, w, h, opening) {
    const topH = h/2 - opening/2;
    const botY = y + opening/2;
    const botH = h/2 - opening/2;

    // Outlines - fill first to erase the beam line underneath
    ctx.fillStyle = 'white';
    ctx.fillRect(x, y - h/2, w, topH);
    ctx.fillRect(x, botY, w, botH);
    ctx.strokeRect(x, y - h/2, w, topH);
    ctx.strokeRect(x, botY, w, botH);

    // Hatching
    const prevLineWidth = ctx.lineWidth;
    ctx.lineWidth = 1.5;
    ctx.beginPath();
    for (let i = x - topH; i < x + w; i += 7) {
        // Top hatch
        ctx.moveTo(i, y - h/2 + topH);
        ctx.lineTo(i + topH, y - h/2);
        // Bottom hatch
        ctx.moveTo(i, botY);
        ctx.lineTo(i + botH, botY + botH);
    }
    ctx.stroke();
    ctx.lineWidth = prevLineWidth;
  }


  // --- Main Drawing Sequence ---

  // 1. Central Beam Line (drawn first so other elements can be on top)
  const chamber_x_start = 340;
  const chamber_w = 420;
  const beam_start_x = 150;
  ctx.lineWidth = 1.5;
  ctx.beginPath();
  ctx.moveTo(beam_start_x, y_center);
  ctx.lineTo(chamber_x_start + chamber_w - 20, y_center);
  ctx.stroke();
  ctx.lineWidth = 2; // Reset


  // 2. Oven
  const oven_x = 80;
  const oven_w = 70;
  const oven_h = 60;
  const oven_opening = 24;
  const oven_thickness = 12;
  
  ctx.save();
  // Create clipping path for the oven wall
  ctx.beginPath();
  ctx.moveTo(oven_x, y_center - oven_h/2);
  ctx.lineTo(oven_x + oven_w, y_center - oven_h/2);
  ctx.lineTo(oven_x + oven_w, y_center - oven_opening/2);
  ctx.lineTo(oven_x + oven_w - oven_thickness, y_center - oven_opening/2);
  ctx.lineTo(oven_x + oven_w - oven_thickness, y_center - oven_h/2 + oven_thickness);
  ctx.lineTo(oven_x + oven_thickness, y_center - oven_h/2 + oven_thickness);
  ctx.lineTo(oven_x + oven_thickness, y_center + oven_h/2 - oven_thickness);
  ctx.lineTo(oven_x + oven_w - oven_thickness, y_center + oven_h/2 - oven_thickness);
  ctx.lineTo(oven_x + oven_w - oven_thickness, y_center + oven_opening/2);
  ctx.lineTo(oven_x + oven_w, y_center + oven_opening/2);
  ctx.lineTo(oven_x + oven_w, y_center + oven_h/2);
  ctx.lineTo(oven_x, y_center + oven_h/2);
  ctx.closePath();
  ctx.stroke();

  // Fill with stipple pattern
  ctx.clip();
  for (let i = 0; i < 400; i++) {
    const dotX = oven_x + Math.random() * oven_w;
    const dotY = (y_center - oven_h / 2) + Math.random() * oven_h;
    if (ctx.isPointInPath(dotX, dotY)) {
        ctx.fillRect(dotX, dotY, 1.5, 1.5);
    }
  }
  ctx.restore();

  // 3. Effusion splash
  const splash_x = oven_x + oven_w;
  const splash_len = 25;
  const splash_angle_range = Math.PI / 1.5;
  ctx.lineWidth = 1;
  for (let i = 0; i < 7; i++) {
    const angle = -splash_angle_range/2 + splash_angle_range * (i/6);
    ctx.beginPath();
    ctx.moveTo(splash_x, y_center);
    ctx.lineTo(splash_x + splash_len * Math.cos(angle), y_center + splash_len * Math.sin(angle));
    ctx.stroke();
  }
  ctx.lineWidth = 2;


  // 4. Collimating Slits
  const slit1_x = 240;
  const slit2_x = 310;
  const slit_w = 20;
  const slit_h = 130;
  const slit_opening = 18;
  drawHatchedSlit(slit1_x, y_center, slit_w, slit_h, slit_opening);
  drawHatchedSlit(slit2_x, y_center, slit_w, slit_h, slit_opening);
  
  // 5. Vacuum Chamber
  const chamber_h = 160;
  ctx.strokeRect(chamber_x_start, y_center - chamber_h/2, chamber_w, chamber_h);


  // 6. Collimated Beam Arrow (drawn on top of the central line)
  const arrow_start_x = 420;
  const arrow_end_x = 550;
  ctx.lineWidth = 3;
  ctx.beginPath();
  ctx.moveTo(arrow_start_x, y_center);
  ctx.lineTo(arrow_end_x, y_center);
  ctx.stroke();
  // Arrowhead
  const head_len = 15;
  ctx.beginPath();
  ctx.moveTo(arrow_end_x + head_len, y_center);
  ctx.lineTo(arrow_end_x, y_center - head_len/2.5);
  ctx.lineTo(arrow_end_x, y_center + head_len/2.5);
  ctx.closePath();
  ctx.fill();
  ctx.lineWidth = 2;

  // 7. Dimension Line
  const dim_y = y_center + chamber_h/2 + 50;
  const dim_start_x = chamber_x_start;
  const dim_end_x = chamber_x_start + chamber_w;
  ctx.lineWidth = 1.5;
  ctx.beginPath();
  ctx.moveTo(dim_start_x, dim_y - 8);
  ctx.lineTo(dim_start_x, dim_y + 8);
  ctx.moveTo(dim_start_x, dim_y);
  ctx.lineTo(dim_end_x, dim_y);
  ctx.moveTo(dim_end_x, dim_y - 8);
  ctx.lineTo(dim_end_x, dim_y + 8);
  ctx.stroke();


  // 8. Labels
  // oven
  ctx.fillText('oven', oven_x + oven_w/2, y_center + oven_h/2 + 30);
  
  // small hole
  const hole_label_x = 130;
  const hole_label_y = 100;
  const hole_target_x = splash_x - 3;
  const hole_target_y = y_center - 8;
  ctx.fillText('small hole', hole_label_x, hole_label_y);
  ctx.lineWidth = 1.5;
  const angle = Math.atan2(hole_target_y - (hole_label_y + 10), hole_target_x - (hole_label_x + 35));
  ctx.beginPath();
  ctx.moveTo(hole_label_x + 35, hole_label_y + 10);
  ctx.lineTo(hole_target_x, hole_target_y);
  ctx.lineTo(hole_target_x - 12 * Math.cos(angle - Math.PI / 8), hole_target_y - 12 * Math.sin(angle - Math.PI / 8));
  ctx.moveTo(hole_target_x, hole_target_y);
  ctx.lineTo(hole_target_x - 12 * Math.cos(angle + Math.PI / 8), hole_target_y - 12 * Math.sin(angle + Math.PI / 8));
  ctx.stroke();
  ctx.lineWidth = 2; // reset
  
  // collimating slits
  ctx.fillText('collimating slits', (slit1_x + slit2_x + slit_w) / 2, y_center - slit_h/2 - 20);

  // collimated beam
  ctx.fillText('collimated beam', arrow_start_x + 65, y_center - 25);

  // vacuum chamber
  ctx.fillText('vacuum chamber', chamber_x_start + chamber_w/2, y_center + chamber_h/2 - 30);

  // 1 m
  ctx.fillText('1 m', chamber_x_start + chamber_w/2, dim_y + 25);
  
  // Fig. 2.45.
  ctx.fillText('Fig. 2.45.', chamber_x_start + chamber_w/2, dim_y + 75);

</script>
</body>
</html>